---
title: Components - Mitosis
---

# Components

## At a glance

Mitosis is inspired by many modern frameworks. You'll see components that look like React components and use React-like hooks, but have simple mutable state like Vue, use a static form of JSX like Solid, compile away like Svelte, and use a simple, prescriptive structure like Angular.

An example of a Mitosis component showing several features:

```tsx
import { For, Show, useStore } from '@builder.io/mitosis';

export default function MyComponent(props) {
  const state = useStore({
    newItemName: 'New item',
    list: ['hello', 'world'],
    addItem() {
      state.list = [...state.list, state.newItemName];
    },
  });

  return (
    <div>
      <Show when={props.showInput}>
        <input
          value={state.newItemName}
          onChange={(event) => (state.newItemName = event.target.value)}
        />
      </Show>
      <div css={{ padding: '10px' }}>
        <button onClick={() => state.addItem()}>Add list item</button>
        <div>
          <For each={state.list}>{(item) => <div>{item}</div>}</For>
        </div>
      </div>
    </div>
  );
}
```

## Components

Mitosis is component-driven like most modern frontend frameworks. Each Mitosis component should be in its own file and be the single default export. They are simple functions that return JSX elements

```tsx
export default function MyComponent() {
  return <div>Hello world!</div>;
}
```

## State

State is provided by the `useStore` hook. Currently, the name of this value must be `state` like below:

```tsx
export default function MyComponent() {
  const state = useStore({
    name: 'Steve',
  });

  return (
    <div>
      <h2>Hello, {state.name}</h2>
      <input
        onInput={(event) => {
          state.name = event.target.value;
        }}
        value={state.name}
      />
    </div>
  );
}
```

If the initial state value is a computed value (whether based on `props` or the output of some function), then you cannot inline it. Instead, use a getter method:

```tsx
export default function MyComponent(props) {
  const state = useStore({
    _name: '',
    get name() {
      // Use the state value if set, otherwise the prop value if set,
      // otherwise the default value of 'Steve'
      return state._name || props.name || 'Steve';
    },
    setName(name: string) {
      state._name = name;
    },
  });

  return (
    <div>
      <h2>Hello, {state.name}</h2>
      <input onInput={(event) => state.setName(event.target.value)} value={state.name} />
    </div>
  );
}
```

Components automatically update when state values change

### useState

Alternatively, you can use the `useState` hook to create a single piece of state

```tsx
export default function MyComponent() {
  const [name, setName] = useState('Steve');

  return (
    <div>
      <h2>Hello, {name}</h2>
      <input onInput={(event) => setName(event.target.value)} value={name} />
    </div>
  );
}
```

## Methods

The state object can also take methods.

```tsx
export default function MyComponent() {
  const state = useStore({
    name: 'Steve',
    updateName(newName) {
      state.name = newName;
    },
  });

  return (
    <div>
      <h2>Hello, {state.name}</h2>
      <input onInput={(event) => state.updateName(event.target.value)} value={state.name} />
    </div>
  );
}
```

## Styling

### `css-in-js`

Styling is done via the `css` prop on DOM elements and components. It takes CSS properties in `camelCase` (like the `style` object on DOM elements) and properties as valid CSS strings

```tsx
export default function CSSExample() {
  return <div css={{ marginTop: '10px', color: 'red' }} />;
}
```

You can also include media queries as keys, with values as style objects

```tsx
export default function ResponsiveExample() {
  return (
    <div
      css={{
        marginTop: '10px',
        '@media (max-width: 500px)': {
          marginTop: '0px',
        },
      }}
    />
  );
}
```

You can also use the [useStyle](/docs/hooks#usestyle) hook to add styles to a component

### `import .css file`

In general all imports inside a Mitosis component are passed to the generated output file.
Therefore, you can import a `.css` file like this:

````css
/* ./src/my-component/my-component.css */


.my-component{
    margin-top: 10px;
}
````

```tsx
/* ./src/my-component/my-component.lite.tsx */
import "./my-component.css";

export default function CSSExample() {
  return <div class="my-component" />;
}
```

> **Note:** The Mitosis cli will only move `.ts` and `.js` files to the output directory.
> You need to move the `.css` file by your own.

### `headless components`

Another approach is to develop your components without a fixed style inside the Mitosis component, a.k.a. "headless components".

You can do so by loading the styles inside the consuming webapp via a bundler (vite, webpack, etc.) or with a head stylesheet `<link rel="stylesheet" ...`.
You can then use `class` or `data-*` attributes inside your Mitosis component to apply those styles:

```tsx
/* ./src/my-component/my-component.lite.tsx */
export default function CSSExample() {
  return <div class="my-component" />;
}
```

## `class` vs `className`

Mitosis prefers that you use `class` to provide class name strings, but it also allows you to provide `className`. If both are used in the same component, it will attempt to merge the two. We recommend that you only use one (preferrably `class`, as that's what is internally preferred by Mitosis).

## Control flow

Control flow in Builder is static like [Solid](https://github.com/ryansolid/solid). Instead of using freeform javascript like in React, you must use control flow components like `<Show>` and `<For>`

### Show

Use `<Show>` for conditional logic. It takes a single `when` prop for the condition to match. When the condition is truthy, the children will render; otherwise, they will not. You can additionally provide an `else` prop for the content to be rendered in case the condition is falsy.

```tsx
export default function MyComponent(props) {
  return (
    <>
      <Show when={props.showContents} else={<span {...props.attributes}>{props.text}</span>}>
        Hello, I may or may not show!
      </Show>
      ;
    </>
  );
}
```

### For

Use `<For>` for repeating items, for instance mapping over an array. It takes a singular `each` prop for the array to iterate over. This component takes a singular function as a child that it passes the relevant item and index to, like below:

```tsx
export default function MyComponent(props) {
  const state = useStore({
    myArray: [1, 2, 3],
  });
  return <For each={state.myArray}>{(theArrayItem, index) => <div>{theArrayItem}</div>}</For>;
}
```

### Children

We use the standard method for passing children with `props.children`

```tsx
export default function MyComponent(props) {
  return <div>{props.children}</div>;
}
```

<details>
  <summary>For <strong>Web Component</strong> you need to use ShadowDom metadata</summary>

```tsx
import { useMetadata } from '@builder.io/mitosis';

useMetadata({
  isAttachedToShadowDom: true,
});
export default function MyComponent(props) {
  return <div>{props.children}</div>;
}
```

</details>

> **Note**: You cannot directly iterate over the children prop. It is a special property intended for rendering like this:

```jsx
<div>{props.children}</div>
````

Many frameworks do not support manipulating or iterating over it directly, unlike frameworks such as React or Vue.

### Fragment

The `Fragment` component accepts the `key` prop, which is typically used when the `Fragment` is the direct child of a `For` loop component.

````tsx
import { For, Fragment } from '@builder.io/mitosis';

export default function BasicForFragment() {
  return (
    <div>
      <For each={['a', 'b', 'c']}>
        {(option) => (
          <Fragment key={`key-${option}`}>
            <span>{option}</span>
          </Fragment>
        )}
      </For>
    </div>
  );
}

````

### Slot

When you want to register a named slot you do so using a prop.

```tsx
<div>
  <Layout
    top={<NavBar/>}
    left={<Sidebar/>}
    center={<Content/>}
  />
    anything else
  </Layout>
</div>
```

In this example we are registering `top`, `left`, and `center` for the `Layout` component to project.

If the `Layout` component was also a Mitosis component then we simply use the reference in the props.

```tsx
export default function Layout(props) {
  return (
    <div className="layout">
      <div className="top">{props.top}</div>
      <div className="left">{props.left}</div>
      <div className="center">{props.center}</div>
      {props.children}
    </div>
  );
}
```

or use the Slot component provided by component

```tsx
import { Slot } from '@builder.io/mitosis';

export default function Layout(props) {
  return (
    <div className="layout">
      <div className="top">
        <Slot name="top" />
      </div>
      <div className="left">
        <Slot name="left" />
      </div>
      <div className="center">
        <Slot name="center" />
      </div>
      <Slot />
    </div>
  );
}
```

For vue component a `slot` prop will be compiled into named slot

```html
<div class="layout">
  <div class="top"><slot name="top" /></div>
  <div class="left"><slot name="left" /></div>
  <div class="center"><slot name="center" /></div>
  <slot />
</div>
}
```

Mitosis compiles one component at a time and is only concerned with outputting the correct method for each framework. For the two examples above, here are the angular and html outputs.

```html
<div>
  <layout>
    <sidebar left></sidebar>
    <nav-bar top></nav-bar>
    <content center></content>
    anything else
  </layout>
  <div></div>
</div>
```

```tsx
@Component({
  selector: 'layout',
  template: `
    <div class="layout">
      <div class="top">
        <ng-content select="[top]"></ng-content>
      </div>
      <div class="left">
        <ng-content select="[left]"></ng-content>
      </div>
      <div class="center">
        <ng-content select="[center]"></ng-content>
      </div>
      <ng-content></ng-content>
    </div>
  `,
})
class LayoutComponent {}
```

In webcomponent you need to use ShadowDom metadata for named slots

<details>
  <summary>For <strong>Web Component</strong> you need to use ShadowDom metadata named slots</summary>

```tsx
import { useMetadata } from '@builder.io/mitosis';

useMetadata({
  isAttachedToShadowDom: true,
});
export default function Layout(props) {
  return (
    <div className="layout">
      <div className="top">{props.top}</div>
      <div className="left">{props.left}</div>
      <div className="center">{props.center}</div>
      {props.children}
    </div>
  );
}
```

</details>

### Default Slot content

```tsx
import { Slot } from '@builder.io/mitosis';

export default function Layout(props) {
  return (
    <div className="layout">
      <div className="top">
        <Slot name="top">Top default</Slot>
      </div>
      <div className="left">
        <Slot name="left" />
      </div>
      <div className="center">
        <Slot name="center" />
      </div>
      <Slot>Default child</Slot>
    </div>
  );
}
```
